package com.bjsj.pro.tools;

import android.app.Activity;
import android.content.Context;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaMetadataRetriever;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.util.Log;


import com.bjsj.pro.tools.Constants;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

import cafe.adriel.androidaudioconverter.AndroidAudioConverter;
import cafe.adriel.androidaudioconverter.callback.IConvertCallback;
import cafe.adriel.androidaudioconverter.callback.ILoadCallback;

/**
 * 录音
 */
public class RecordUtils {
    private AudioRecord mAudioRecord;
    private Integer mRecordBufferSize;
    private File handlerWavFile;
    private String path;
    private Activity activity;
    private static RecordUtils recordUtils;
    private static boolean isQuit;
    private static String str_time;
    private OnTranscodingListener onTranscodingListener;

    public static RecordUtils getInstance(Activity activity) {
        if (recordUtils == null || recordUtils.isQuit) {
            recordUtils = new RecordUtils(activity);
        }
        return recordUtils;
    }

    public RecordUtils(Activity activity) {
        this.activity = activity;
        initMinBufferSize();
        initAudioRecord();
        path = Constants.VOICE_FILE;
        Log.d("yyyyyyyyyyyyyyy",path);
//        path = activity.getExternalFilesDir("").getAbsolutePath() + "/voice/";
    }

    public static void init(Context context) {
        //音频转码
        AndroidAudioConverter.load(context, new ILoadCallback() {
            @Override
            public void onSuccess() {

            }

            @Override
            public void onFailure(Exception error) {

            }
        });
    }

    /**
     * 初始化配置
     */
    private void initAudioRecord() {
        mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC // 音频源,MIC代表麦克风
                , 8000 //采样率（赫兹）
                , AudioFormat.CHANNEL_IN_MONO //声道配置
                , AudioFormat.ENCODING_PCM_16BIT //音频格式
                , mRecordBufferSize); //缓存区大小
      /*  int sampleRate = 8000;
        int channel = AudioFormat.CHANNEL_IN_MONO;
        int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
        int bufferSize = 4 * AudioRecord.getMinBufferSize(sampleRate, channel, audioFormat);

       mAudioRecord=new AudioRecord(MediaRecorder.AudioSource.CAMCORDER, sampleRate, channel, audioFormat, bufferSize);*/
    }

    private void initMinBufferSize() {
        //获取每一帧的字节流大小
        mRecordBufferSize = AudioRecord.getMinBufferSize(8000
                , AudioFormat.CHANNEL_IN_MONO
                , AudioFormat.ENCODING_PCM_16BIT);
    }

    private boolean mWhetherRecord;
    private File pcmFile;


    public void closeRecord(){
        mAudioRecord.stop();
        Log.d("wwwwwwwwwwwww","停止录制");
    }

    /**
     * 开始录音
     */
    public void startRecord() {
        File file = new File(path);
        if (!file.exists()) {
            file.mkdirs();
        }
        pcmFile = new File(path, "audioRecord.pcm");
        mWhetherRecord = true;
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    mAudioRecord.startRecording();//开始录制
                    Log.d("wwwwwwwwwwww","录制中");
                } catch (IllegalStateException e) {
                    Log.i("RecordUtils", e.toString());
                }
                FileOutputStream fileOutputStream = null;
                try {
                    fileOutputStream = new FileOutputStream(pcmFile);
                    byte[] bytes = new byte[mRecordBufferSize];
                    while (mWhetherRecord) {
                        mAudioRecord.read(bytes, 0, bytes.length);//读取流
                        fileOutputStream.write(bytes);
                        fileOutputStream.flush();
                    }
                    try {
                        mAudioRecord.stop();//停止录制
                        Log.d("wwwwwwwwwwwww","停止录制");
                    } catch (IllegalStateException e) {
                       // Log.d("ffffffffffff","停止录制");
                        Log.d("fffffffffff", e.toString());
                    }
                    fileOutputStream.flush();
                    fileOutputStream.close();
                    addHeadData();//添加音频头部信息并且转成wav格式
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                    mAudioRecord.stop();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        }).start();
    }

    private String getPath() {
        return path + str_time + ".mp3";
    }

    /**
     * 结束录音并把wav转成mp3
     */
    public void stopRecord() {
        mWhetherRecord = false;
        isQuit = true;
        mAudioRecord.release();
        Log.d("wwwwwwww","wav转mp3");
        final IConvertCallback callback = new IConvertCallback() {
            @Override
            public void onSuccess(File convertedFile) {
                handlerWavFile.delete();
                pcmFile.delete();
                onTranscodingListener.complete(getPath(), 0);
            }

            @Override
            public void onFailure(Exception error) {
                Log.d("轉碼失败",error.toString());
            }
        };
        final Handler mHandler = new Handler();
        Runnable r = new Runnable() {

            @Override
            public void run() {
                AndroidAudioConverter.with(activity)
                        .setFile(handlerWavFile)
                        .setFormat(cafe.adriel.androidaudioconverter.model.AudioFormat.MP3)
                        .setCallback(callback)
                        .convert();
            }
        };
        //延迟0.1秒转换，不然有可能获取不到
        mHandler.postDelayed(r, 100);//延时100毫秒
    }

    //添加文件头
    private void addHeadData() {
        pcmFile = new File(path, "audioRecord.pcm");
        str_time = millis2String(System.currentTimeMillis(), getDateFormat("yyyy-MM-dd HH:mm:ss"));
        handlerWavFile = new File(path, str_time + ".wav");
        PcmToWavUtil pcmToWavUtil = new PcmToWavUtil(8000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
        pcmToWavUtil.pcmToWav(pcmFile.toString(), handlerWavFile.toString());
    }


    private static final ThreadLocal<SimpleDateFormat> SDF_THREAD_LOCAL = new ThreadLocal<>();
    private static SimpleDateFormat getDateFormat(String pattern) {
        SimpleDateFormat simpleDateFormat = SDF_THREAD_LOCAL.get();
        if (simpleDateFormat == null) {
            simpleDateFormat = new SimpleDateFormat(pattern, Locale.getDefault());
            SDF_THREAD_LOCAL.set(simpleDateFormat);
        } else {
            simpleDateFormat.applyPattern(pattern);
        }
        return simpleDateFormat;
    }

    public static String millis2String(final long millis, @NonNull final DateFormat format) {
        return format.format(new Date(millis));
    }


    /**
     * 将pcm转成wav
     */
    public class PcmToWavUtil {
        private static final String TAG = "PcmToWavUtil";

        /**
         * 缓存的音频大小
         */
        private int mBufferSize;
        /**
         * 采样率
         */
        private int mSampleRate;
        /**
         * 声道数
         */
        private int mChannel;


        /**
         * @param sampleRate sample rate、采样率
         * @param channel    channel、声道
         * @param encoding   Audio data format、音频格式
         */
        PcmToWavUtil(int sampleRate, int channel, int encoding) {
            this.mSampleRate = sampleRate;
            this.mChannel = channel;
            this.mBufferSize = AudioRecord.getMinBufferSize(mSampleRate, mChannel, encoding);
        }


        /**
         * pcm文件转wav文件
         *
         * @param inFilename  源文件路径
         * @param outFilename 目标文件路径
         */
        void pcmToWav(String inFilename, String outFilename) {
            FileInputStream in;
            FileOutputStream out;
            long totalAudioLen;//总录音长度
            long totalDataLen;//总数据长度
            long longSampleRate = mSampleRate;
            int channels = mChannel == AudioFormat.CHANNEL_IN_MONO ? 1 : 2;
            long byteRate = 16 * mSampleRate * channels / 8;
            byte[] data = new byte[mBufferSize];
            try {
                in = new FileInputStream(inFilename);
                out = new FileOutputStream(outFilename);
                totalAudioLen = in.getChannel().size();
                totalDataLen = totalAudioLen + 36;

                writeWaveFileHeader(out, totalAudioLen, totalDataLen,
                        longSampleRate, channels, byteRate);
                while (in.read(data) != -1) {
                    out.write(data);
                    out.flush();

                }
                Log.e(TAG, "pcmToWav: 停止处理");
                in.close();
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }


        /**
         * 加入wav文件头
         */
        private void writeWaveFileHeader(FileOutputStream out, long totalAudioLen,
                                         long totalDataLen, long longSampleRate, int channels, long byteRate)
                throws IOException {
            byte[] header = new byte[44];
            // RIFF/WAVE header
            header[0] = 'R';
            header[1] = 'I';
            header[2] = 'F';
            header[3] = 'F';
            header[4] = (byte) (totalDataLen & 0xff);
            header[5] = (byte) ((totalDataLen >> 8) & 0xff);
            header[6] = (byte) ((totalDataLen >> 16) & 0xff);
            header[7] = (byte) ((totalDataLen >> 24) & 0xff);
            //WAVE
            header[8] = 'W';
            header[9] = 'A';
            header[10] = 'V';
            header[11] = 'E';
            // 'fmt ' chunk
            header[12] = 'f';
            header[13] = 'm';
            header[14] = 't';
            header[15] = ' ';
            // 4 bytes: size of 'fmt ' chunk
            header[16] = 16;
            header[17] = 0;
            header[18] = 0;
            header[19] = 0;
            // format = 1
            header[20] = 1;
            header[21] = 0;
            header[22] = (byte) channels;
            header[23] = 0;
            header[24] = (byte) (longSampleRate & 0xff);
            header[25] = (byte) ((longSampleRate >> 8) & 0xff);
            header[26] = (byte) ((longSampleRate >> 16) & 0xff);
            header[27] = (byte) ((longSampleRate >> 24) & 0xff);
            header[28] = (byte) (byteRate & 0xff);
            header[29] = (byte) ((byteRate >> 8) & 0xff);
            header[30] = (byte) ((byteRate >> 16) & 0xff);
            header[31] = (byte) ((byteRate >> 24) & 0xff);
            // block align
            header[32] = (byte) (2 * 16 / 8);
            header[33] = 0;
            // bits per sample
            header[34] = 16;
            header[35] = 0;
            //data
            header[36] = 'd';
            header[37] = 'a';
            header[38] = 't';
            header[39] = 'a';
            header[40] = (byte) (totalAudioLen & 0xff);
            header[41] = (byte) ((totalAudioLen >> 8) & 0xff);
            header[42] = (byte) ((totalAudioLen >> 16) & 0xff);
            header[43] = (byte) ((totalAudioLen >> 24) & 0xff);
            out.write(header, 0, 44);
        }
    }

    /**
     * 获取文件大小
     *
     * @param videoPath 路径
     * @return 时长
     */
    private int getLocalVideoDuration(String videoPath) {
        int duration;
        try {
            MediaMetadataRetriever mmr = new MediaMetadataRetriever();
            mmr.setDataSource(videoPath);
            duration = Integer.parseInt(mmr.extractMetadata
                    (MediaMetadataRetriever.METADATA_KEY_DURATION));
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
        return duration;
    }

    /**
     * 设置转码完成的监听
     *
     * @param onTranscodingListener
     */
    public void setOnTranscodingListener(OnTranscodingListener onTranscodingListener) {
        this.onTranscodingListener = onTranscodingListener;
    }

    public interface OnTranscodingListener {
        void complete(String path, int duration);
    }

    public static void playMusic(String pathStr, final Activity activity) {
        MediaPlayer mediaPlayer = new MediaPlayer();
        if (mediaPlayer.isPlaying()) {
            mediaPlayer.stop();
            mediaPlayer.release();
            mediaPlayer = new MediaPlayer();
        }
        try {
            mediaPlayer.reset();
            mediaPlayer.setDataSource(pathStr);
            //3 准备播放
            mediaPlayer.prepareAsync();
            mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                @Override
                public void onPrepared(final MediaPlayer mediaPlayer) {
                    activity.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            mediaPlayer.start();
                        }
                    });
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
